home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 3 / Gold Medal Software - Volume 3 (Gold Medal) (1994).iso / archive / cx201e.arj / CXSUB.PAS < prev    next >
Pascal/Delphi Source File  |  1994-03-01  |  13KB  |  463 lines

  1. {
  2.    CXSUB functions.
  3.    Copyright (c) 1990-1994 Eugene Nelson, Four Lakes Computing.
  4.  
  5.    This file contains useful subroutines that may be used with Cx.
  6.    See file CXSUB.DOC for interface information.
  7. }
  8.  
  9. unit  cxsub;
  10.  
  11. {$F+}          {Required, do not change}
  12. {$I-}          {Required, do not change}
  13.  
  14. {
  15.    The following notes apply to the Pascal implementation of CXSUB:
  16.  
  17.       *  cx_decompress_ofile has another parameter, named extract,
  18.          which is used to indicate if the output file should be
  19.          written to (True or False).  If False, cx_decompress_ofile
  20.          may be used as an integrity checker.
  21.  
  22.       *  A callback type, cxback, is used for progress and interrupt
  23.          control  A callback function and an application specific
  24.          pointer are passed to the CXSUB file compression routines.
  25.          See file CXF.PAS for usage examples.
  26.  
  27.       *  The CXSUB functions 'trap' all out of memory and I/O
  28.          error conditions.  These errors are returned as CXSUB_ERR*.
  29. }
  30.    
  31. interface uses cx;
  32. {------------------------------------------------------------------------}
  33.  
  34. const CXSUB_ERR_OPENS =       1;
  35. const CXSUB_ERR_OPEND =       2;
  36. const CXSUB_ERR_NOMEM =       3;
  37. const CXSUB_ERR_READ =        4;
  38. const CXSUB_ERR_WRITE =       5;
  39. const CXSUB_ERR_CLOSE =       6;
  40. const CXSUB_ERR_INVALID =     7;
  41.  
  42. type cxback = function(p: pointer): integer;
  43.  
  44. function cx_error_message(
  45.                   err      :CXINT)     : string;
  46.  
  47. function cx_compress_ofile(
  48.             var   ofile    :file       ;
  49.             var   ifile    :file       ;
  50.                   method   :CXINT      ;
  51.                   bsize    :CXINT      ;
  52.                   tsize    :CXINT      ;
  53.                   callback :cxback     ;
  54.                   p        :pointer)   : CXINT;
  55.  
  56. function cx_compress_file(
  57.                   dst      :string     ;
  58.                   src      :string     ;
  59.                   method   :CXINT      ;
  60.                   bsize    :CXINT      ;
  61.                   tsize    :CXINT      ;
  62.                   callback :cxback     ;
  63.                   p        :pointer)   : CXINT;
  64.  
  65. function cx_decompress_ofile(
  66.             var   ofile    :file       ;
  67.             var   ifile    :file       ;
  68.                   extract  :boolean    ;
  69.                   callback :cxback     ;
  70.                   p        :pointer)   : CXINT;
  71.  
  72. function cx_decompress_file(
  73.                   dst      :string     ;
  74.                   src      :string     ;
  75.                   callback :cxback     ;
  76.                   p        :pointer)   : CXINT;
  77.  
  78. implementation
  79.  
  80. {function cx_heap_func is used to avoid out of memory runtime errors}
  81. {------------------------------------------------------------------------}
  82. function cx_heap_func(size: word): integer;
  83. begin
  84.    cx_heap_func:= 1;
  85. end;
  86.  
  87. {------------------------------------------------------------------------}
  88. function cx_error_message(
  89.                   err      :CXINT)     : string;
  90. begin
  91.    case err of
  92.       CX_ERR_INVALID:    cx_error_message:= 'data could not be decompressed';
  93.       CX_ERR_METHOD:     cx_error_message:= 'invalid compression method';
  94.       CX_ERR_BUFFSIZE:   cx_error_message:= 'invalid buffer size';
  95.       CX_ERR_TEMPSIZE:   cx_error_message:= 'invalid temp buffer size';
  96.       CXSUB_ERR_OPENS:   cx_error_message:= 'could not open source';
  97.       CXSUB_ERR_OPEND:   cx_error_message:= 'could not open destination';
  98.       CXSUB_ERR_NOMEM:   cx_error_message:= 'insufficient memory';
  99.       CXSUB_ERR_READ:    cx_error_message:= 'could not read from source';
  100.       CXSUB_ERR_WRITE:   cx_error_message:= 'could not write to destination';
  101.       CXSUB_ERR_CLOSE:   cx_error_message:= 'could not close destination';
  102.       CXSUB_ERR_INVALID: cx_error_message:= 'source file is invalid or corrupt';
  103.       else               cx_error_message:= 'unknown';
  104.    end;
  105. end;
  106.  
  107. {------------------------------------------------------------------------}
  108. function cx_compress_pofile(
  109.             var   ofile    :file       ;
  110.             var   ifile    :file       ;
  111.                   ibuff    :pointer    ;
  112.                   obuff    :pointer    ;
  113.                   tbuff    :pointer    ;
  114.                   method   :CXINT      ;
  115.                   bsize    :CXINT      ;
  116.                   tsize    :CXINT      ;
  117.                   callback :cxback     ;
  118.                   p        :pointer)   : CXINT;
  119. var
  120.    t: pointer;
  121.    j, k, crc: CXINT;
  122.  
  123. begin
  124.    repeat
  125.       if callback(p) <> 0
  126.          then begin
  127.             cx_compress_pofile:= 0;
  128.             exit;
  129.          end;
  130.  
  131.       BlockRead(ifile, ibuff^, bsize, j);
  132.       if IOResult <> 0
  133.       then begin
  134.          cx_compress_pofile:= CXSUB_ERR_READ;
  135.          exit;
  136.       end;
  137.  
  138.       BlockWrite(ofile, j, CXINTSIZE);
  139.       if IOResult <> 0
  140.       then begin
  141.          cx_compress_pofile:= CXSUB_ERR_WRITE;
  142.          exit;
  143.       end;
  144.  
  145.       if j <> 0
  146.       then begin
  147.          k:= CX_COMPRESS(method, obuff^, bsize, ibuff^, j, tbuff^, tsize);
  148.          if k > j
  149.          then begin
  150.             cx_compress_pofile:= k;
  151.             exit;
  152.          end;
  153.  
  154.          BlockWrite(ofile, k, CXINTSIZE);
  155.          if IOResult <> 0
  156.          then begin
  157.             cx_compress_pofile:= CXSUB_ERR_WRITE;
  158.             exit;
  159.          end;
  160.  
  161.          if k = j       {block could not be compressed}
  162.             then t:= ibuff
  163.             else t:= obuff;
  164.  
  165.          crc:= CX_CRC(t^, k);
  166.  
  167.          BlockWrite(ofile, crc, CXINTSIZE);
  168.          if IOResult <> 0
  169.          then begin
  170.             cx_compress_pofile:= CXSUB_ERR_WRITE;
  171.             exit;
  172.          end;
  173.  
  174.          BlockWrite(ofile, t^, k);
  175.          if IOResult <> 0
  176.          then begin
  177.             cx_compress_pofile:= CXSUB_ERR_WRITE;
  178.             exit;
  179.          end;
  180.       end;
  181.    until j = 0;
  182.  
  183.    cx_compress_pofile:= 0;
  184. end;
  185.  
  186.  
  187. {------------------------------------------------------------------------}
  188. function cx_compress_ofile(
  189.             var   ofile    :file       ;
  190.             var   ifile    :file       ;
  191.                   method   :CXINT      ;
  192.                   bsize    :CXINT      ;
  193.                   tsize    :CXINT      ;
  194.                   callback :cxback     ;
  195.                   p        :pointer)   : CXINT;
  196. var
  197.    ibuff, obuff, tbuff: pointer;
  198.    err: CXINT;
  199.  
  200. begin
  201.    HeapError:= @cx_heap_func;       {trap out of memory conditions}
  202.  
  203.    GetMem(ibuff, bsize);
  204.    GetMem(obuff, bsize+CX_SLOP);
  205.    GetMem(tbuff, tsize);
  206.  
  207.    HeapError:= nil;                 {restore heap error handler}
  208.  
  209.    if (ibuff = nil) or (obuff = nil) or (tbuff = nil)
  210.    then begin
  211.       if ibuff <> nil then FreeMem(ibuff, bsize);
  212.       if obuff <> nil then FreeMem(obuff, bsize+CX_SLOP);
  213.       if tbuff <> nil then FreeMem(tbuff, tsize);
  214.       cx_compress_ofile:= CXSUB_ERR_NOMEM;
  215.       Exit;
  216.    end;
  217.  
  218.    cx_compress_ofile:= cx_compress_pofile(ofile, ifile, ibuff, obuff, tbuff,
  219.                         method, bsize, tsize, callback, p);
  220.  
  221.    FreeMem(ibuff, bsize);
  222.    FreeMem(obuff, bsize+CX_SLOP);
  223.    FreeMem(tbuff, tsize);
  224. end;
  225.  
  226.  
  227. {------------------------------------------------------------------------}
  228. function cx_compress_file(
  229.                   dst      :string     ;
  230.                   src      :string     ;
  231.                   method   :CXINT      ;
  232.                   bsize    :CXINT      ;
  233.                   tsize    :CXINT      ;
  234.                   callback :cxback     ;
  235.                   p        :pointer)   : CXINT;
  236. var
  237.    ifile, ofile: file;
  238.    j, k: CXINT;
  239.  
  240. begin
  241.    Assign(ifile, src);
  242.    Reset(ifile, 1);
  243.    if IOResult <> 0
  244.    then begin
  245.       cx_compress_file:= CXSUB_ERR_OPENS;
  246.       exit;
  247.    end;
  248.  
  249.    Assign(ofile, dst);
  250.    Rewrite(ofile, 1);
  251.    if IOResult <> 0
  252.    then begin
  253.       Close(ifile);
  254.       cx_compress_file:= CXSUB_ERR_OPEND;
  255.       exit;
  256.    end;
  257.  
  258.    k:= cx_compress_ofile(ofile, ifile, method, bsize, tsize, callback, p);
  259.  
  260.    Close(ifile);
  261.    j:= IOResult;     {to clear any input file close IOresult}
  262.  
  263.    Close(ofile);
  264.    if IOResult = 0
  265.       then j:= 0
  266.       else j:= CXSUB_ERR_CLOSE;
  267.  
  268.    if k = 0
  269.       then cx_compress_file:= j
  270.       else cx_compress_file:= k;
  271. end;
  272.  
  273.  
  274. {------------------------------------------------------------------------}
  275. function cx_decompress_pofile(
  276.             var   ofile    :file       ;
  277.             var   ifile    :file       ;
  278.                   extract  :boolean    ;
  279.                   ibuff    :pointer    ;
  280.                   obuff    :pointer    ;
  281.                   tbuff    :pointer    ;
  282.                   callback :cxback     ;
  283.                   p        :pointer)   : CXINT;
  284. var
  285.    bsize,  j, k, crc: CXINT;
  286.    t: pointer;
  287.  
  288. begin
  289.    repeat
  290.       BlockRead(ifile, j, CXINTSIZE);
  291.       if IOResult <> 0
  292.       then begin
  293.          cx_decompress_pofile:= CXSUB_ERR_READ;
  294.          exit;
  295.       end;
  296.  
  297.       if j <> 0
  298.       then begin
  299.          if callback(p) <> 0
  300.             then begin
  301.                cx_decompress_pofile:= 0;
  302.                exit;
  303.             end;
  304.  
  305.          BlockRead(ifile, k, CXINTSIZE);
  306.          if IOResult <> 0
  307.          then begin
  308.             cx_decompress_pofile:= CXSUB_ERR_READ;
  309.             exit;
  310.          end;
  311.  
  312.          if (k > j) or (k > CX_MAX_BUFFER) or (j > CX_MAX_BUFFER)
  313.          then begin
  314.             cx_decompress_pofile:= CXSUB_ERR_INVALID;
  315.             exit;
  316.          end;
  317.  
  318.          BlockRead(ifile, crc, CXINTSIZE);
  319.          if IOResult <> 0
  320.          then begin
  321.             cx_decompress_pofile:= CXSUB_ERR_READ;
  322.             exit;
  323.          end;
  324.  
  325.          BlockRead(ifile, ibuff^, k);
  326.          if IOResult <> 0
  327.          then begin
  328.             cx_decompress_pofile:= CXSUB_ERR_READ;
  329.             exit;
  330.          end;
  331.  
  332.          if CX_CRC(ibuff^, k) <> crc
  333.          then begin
  334.             cx_decompress_pofile:= CXSUB_ERR_INVALID;
  335.             exit;
  336.          end;
  337.  
  338.          if j = k
  339.             then t:= ibuff
  340.             else begin
  341.                k:= CX_DECOMPRESS(obuff^, CX_MAX_BUFFER, ibuff^, k, tbuff^, CX_D_MINTEMP);
  342.                if k > CX_MAX_BUFFER
  343.                then begin
  344.                   cx_decompress_pofile:= k;
  345.                   exit;
  346.                end;
  347.  
  348.                if j <> k
  349.                then begin
  350.                   cx_decompress_pofile:= CXSUB_ERR_INVALID;
  351.                   exit;
  352.                end;
  353.  
  354.                t:= obuff;
  355.             end;
  356.  
  357.          if extract
  358.          then begin
  359.             BlockWrite(ofile, obuff^, j);
  360.             if IOResult <> 0
  361.             then begin
  362.                cx_decompress_pofile:= CXSUB_ERR_WRITE;
  363.                exit;
  364.             end;
  365.          end;
  366.       end;
  367.    until j = 0;
  368.  
  369.    cx_decompress_pofile:= 0;
  370. end;
  371.  
  372. {------------------------------------------------------------------------}
  373. function cx_decompress_ofile(
  374.             var   ofile    :file       ;
  375.             var   ifile    :file       ;
  376.                   extract  :boolean    ;
  377.                   callback :cxback     ;
  378.                   p        :pointer)   : CXINT;
  379. var
  380.    ibuff, obuff, tbuff: pointer;
  381.    err: CXINT;
  382.  
  383. begin
  384.    HeapError:= @cx_heap_func;       {trap out of memory conditions}
  385.  
  386.    GetMem(ibuff, CX_MAX_BUFFER+CX_SLOP);
  387.    GetMem(obuff, CX_MAX_BUFFER);
  388.    GetMem(tbuff, CX_D_MINTEMP);
  389.  
  390.    HeapError:= nil;                 {restore  heap error handler}
  391.  
  392.    if (ibuff = nil) or (obuff = nil) or (tbuff = nil)
  393.    then begin
  394.       if ibuff <> nil then FreeMem(ibuff, CX_MAX_BUFFER+CX_SLOP);
  395.       if obuff <> nil then FreeMem(obuff, CX_MAX_BUFFER);
  396.       if tbuff <> nil then FreeMem(tbuff, CX_D_MINTEMP);
  397.       cx_decompress_ofile:= CXSUB_ERR_NOMEM;
  398.       Exit;
  399.    end;
  400.  
  401.    cx_decompress_ofile:= cx_decompress_pofile(ofile, ifile, extract,
  402.                            ibuff, obuff, tbuff, callback, p);
  403.  
  404.    FreeMem(ibuff, CX_MAX_BUFFER+CX_SLOP);
  405.    FreeMem(obuff, CX_MAX_BUFFER);
  406.    FreeMem(tbuff, CX_D_MINTEMP);
  407. end;
  408.  
  409. {------------------------------------------------------------------------}
  410. function cx_decompress_file(
  411.                   dst      :string     ;
  412.                   src      :string     ;
  413.                   callback :cxback     ;
  414.                   p        :pointer)   : CXINT;
  415. var
  416.    ifile, ofile: file;
  417.    extract: boolean;
  418.    j, k: CXINT;
  419.  
  420. begin
  421.    Assign(ifile, src);
  422.    Reset(ifile, 1);
  423.    if IOResult <> 0
  424.    then begin
  425.       cx_decompress_file:= CXSUB_ERR_OPENS;
  426.       exit;
  427.    end;
  428.  
  429.    if dst = ''
  430.    then extract:= False
  431.    else begin
  432.       extract:= True;
  433.       Assign(ofile, dst);
  434.       Rewrite(ofile, 1);
  435.       if IOResult <> 0
  436.       then begin
  437.          Close(ifile);
  438.          cx_decompress_file:= CXSUB_ERR_OPEND;
  439.          exit;
  440.       end;
  441.    end;
  442.  
  443.    k:= cx_decompress_ofile(ofile, ifile, extract, callback, p);
  444.  
  445.    Close(ifile);
  446.    j:= IOResult;     {to clear any input file close IOresult}
  447.  
  448.    if not extract
  449.       then j:= 0
  450.       else begin
  451.          Close(ofile);
  452.          if IOResult = 0
  453.             then j:= 0
  454.             else j:= CXSUB_ERR_CLOSE;
  455.       end;
  456.  
  457.    if k = 0
  458.       then cx_decompress_file:= j
  459.       else cx_decompress_file:= k;
  460. end;
  461.  
  462. end.
  463.